]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
st-theme-node: let paint states take weak ref on theme nodes
authorLionel Landwerlin <llandwerlin@gmail.com>
Wed, 10 Jul 2013 09:22:07 +0000 (10:22 +0100)
committerLionel Landwerlin <llandwerlin@gmail.com>
Wed, 10 Jul 2013 19:27:38 +0000 (20:27 +0100)
When the St theme is changed, the StThemeContext unrefs all the theme
nodes cached in it's internal hash table, then emits a signal to
notify all theme nodes that the current theme has changed.

The problem is that the first StWidget to catch a theme changed signal
will trigger a "style-changed" signal catched by its children first.
So the theme changed signal can't be processed properly to cleanup
StThemeNodePaintState before recomputing the theme.

This patch adds a weak ref to the StThemeNode in the
StThemeNodePaintState to ensure paint states are properly cleaned up
when the associated StThemeNode is freed.

https://bugzilla.gnome.org/show_bug.cgi?id=703859

src/st/st-theme-node-drawing.c
src/st/st-theme-node.h

index 0b76f6b2d676da6e091a958c34f4950512cd252d..e8ba869d3f67ca627a98dc7fc9d38e7cf7680fea 100644 (file)
@@ -1391,7 +1391,7 @@ st_theme_node_render_resources (StThemeNodePaintState *state,
    */
   st_theme_node_paint_state_free (state);
 
-  state->node = node;
+  st_theme_node_paint_state_set_node (state, node);
   state->alloc_width = width;
   state->alloc_height = height;
 
@@ -1526,7 +1526,7 @@ st_theme_node_update_resources (StThemeNodePaintState *state,
         }
     }
 
-  state->node = node;
+  st_theme_node_paint_state_set_node (state, node);
   state->alloc_width = width;
   state->alloc_height = height;
 
@@ -2523,8 +2523,9 @@ st_theme_node_paint (StThemeNode           *node,
     }
 }
 
-void
-st_theme_node_paint_state_free (StThemeNodePaintState *state)
+static void
+st_theme_node_paint_state_node_free_internal (StThemeNodePaintState *state,
+                                              gboolean               unref_node)
 {
   int corner_id;
 
@@ -2539,9 +2540,39 @@ st_theme_node_paint_state_free (StThemeNodePaintState *state)
     if (state->corner_material[corner_id] != COGL_INVALID_HANDLE)
       cogl_handle_unref (state->corner_material[corner_id]);
 
+  if (unref_node)
+    st_theme_node_paint_state_set_node (state, NULL);
+
   st_theme_node_paint_state_init (state);
 }
 
+static void
+st_theme_node_paint_state_node_freed (StThemeNodePaintState *state)
+{
+  st_theme_node_paint_state_node_free_internal (state, FALSE);
+}
+
+void
+st_theme_node_paint_state_set_node (StThemeNodePaintState *state, StThemeNode *node)
+{
+  if (state->node)
+    g_object_weak_unref (G_OBJECT (state->node),
+                         (GWeakNotify) st_theme_node_paint_state_node_freed,
+                         state);
+
+  state->node = node;
+  if (state->node)
+    g_object_weak_ref (G_OBJECT (state->node),
+                       (GWeakNotify) st_theme_node_paint_state_node_freed,
+                       state);
+}
+
+void
+st_theme_node_paint_state_free (StThemeNodePaintState *state)
+{
+  st_theme_node_paint_state_node_free_internal (state, TRUE);
+}
+
 void
 st_theme_node_paint_state_init (StThemeNodePaintState *state)
 {
@@ -2567,7 +2598,7 @@ st_theme_node_paint_state_copy (StThemeNodePaintState *state,
 
   st_theme_node_paint_state_free (state);
 
-  state->node = other->node;
+  st_theme_node_paint_state_set_node (state, other->node);
 
   state->alloc_width = other->alloc_width;
   state->alloc_height = other->alloc_height;
index 8f3a378107bc430fccc2229f7be37d57cb5b47f1..5fffa634384be0dfb908db463ba435c6fc064207 100644 (file)
@@ -281,6 +281,8 @@ void st_theme_node_paint_state_free (StThemeNodePaintState *state);
 void st_theme_node_paint_state_copy (StThemeNodePaintState *state,
                                      StThemeNodePaintState *other);
 void st_theme_node_paint_state_invalidate (StThemeNodePaintState *state);
+void st_theme_node_paint_state_set_node (StThemeNodePaintState *state,
+                                         StThemeNode           *node);
 
 G_END_DECLS